{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "#请先运行此代码\n",
    "from IPython.core.interactiveshell import InteractiveShell\n",
    "InteractiveShell.ast_node_interactivity = \"all\" \n",
    "#这玩意可以让代码块分行输出"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 调用函数\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 绝对值和最大值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "abs(-20)#取个绝对值而已\n",
    "max(2, 3, 1, -5)#找最大值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 常用类型转换"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "12.34"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int(12.34)\n",
    "str(1.23)\n",
    "bool(1)\n",
    "bool('')\n",
    "float('12.34')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 定义函数\n",
    "### 函数例子（求绝对值函数）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "999"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def my_abs(x):#定义函数\n",
    "    if x >= 0:\n",
    "        return x\n",
    "    else:\n",
    "        return -x\n",
    "my_abs(-999)#这边就调用函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 空函数\n",
    "* 如果想定义一个什么事也不做的空函数，可以用pass语句"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def nop():#啥都不发生\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "if 20 >= 18:\n",
    "    pass  #还没想好写啥就放个pass在这里"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 参数检查\n",
    "* 如何让上面的my_abs函数对参数类型检测，比如只允许整数和浮点数类型的参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def my_abs(x):\n",
    "    if not isinstance(x, (int, float)):\n",
    "        raise TypeError('操作数类型错啦')\n",
    "    if x >= 0:\n",
    "        return x\n",
    "    else:\n",
    "        return -x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 这就写个BUG看看错误"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "操作数类型错啦",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_9268/3790392476.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mmy_abs\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'A'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_9268/2364621262.py\u001b[0m in \u001b[0;36mmy_abs\u001b[1;34m(x)\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mmy_abs\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      2\u001b[0m     \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mint\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfloat\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m         \u001b[1;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'操作数类型错啦'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      4\u001b[0m     \u001b[1;32mif\u001b[0m \u001b[0mx\u001b[0m \u001b[1;33m>=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m         \u001b[1;32mreturn\u001b[0m \u001b[0mx\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mTypeError\u001b[0m: 操作数类型错啦"
     ]
    }
   ],
   "source": [
    "my_abs('A')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 返回多个值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "\n",
    "def move(x, y, step, angle=0):\n",
    "    nx = x + step * math.cos(angle)\n",
    "    ny = y - step * math.sin(angle)\n",
    "    return nx, ny  #函数是可以返回两个值的\n",
    "\n",
    "x, y = move(100, 100, 60, math.pi / 6)#调用函数获得返回值\n",
    "print(x, y)#print也可以同时打印两个值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**纳尼，这居然是一种假象，Python函数返回的仍然是单一值**（因为返回值是一个元组）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(151.96152422706632, 70.0)\n"
     ]
    }
   ],
   "source": [
    "r = move(100, 100, 60, math.pi / 6)\n",
    "print(r)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 函数的参数\n",
    "### 带默认参数函数例子（计算n次幂）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "125"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "25"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def power(x, n=2):#默认情况下是计算平方的\n",
    "    s = 1\n",
    "    while n > 0:\n",
    "        n = n - 1\n",
    "        s = s * x\n",
    "    return s\n",
    "power(5, 3)#5的3次幂\n",
    "power(5)#所以只用一个参数的情况下，n是默认为2的"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 调用函数，默认参数中只重新设置城市，其他默认"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "name: 木青羽\n",
      "gender: 男\n",
      "age: 6\n",
      "city: 秦皇岛\n"
     ]
    }
   ],
   "source": [
    "def enroll(name, gender, age=6, city='Beijing'):\n",
    "    print('name:', name)\n",
    "    print('gender:', gender)\n",
    "    print('age:', age)\n",
    "    print('city:', city)\n",
    "\n",
    "enroll(\"木青羽\",\"男\",city=\"秦皇岛\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## **关于函数调用的一个坑**\n",
    "这里每次调用默认参数时，都是往L指向的对象加东西，所以越加越多？？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['END']"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "['END', 'END']"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "['END', 'END', 'END']"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def add_end(L=[]):\n",
    "    L.append('END')\n",
    "    return L\n",
    "add_end()\n",
    "add_end()\n",
    "add_end()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['hi', 'END']"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "['hi', 'END', 'END']"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "['hi', 'END', 'END', 'END']"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def add_end(L=[\"hi\"]):#这样写应该好理解点\n",
    "    L.append('END')\n",
    "    return L\n",
    "add_end()\n",
    "add_end()\n",
    "add_end()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### **定义默认参数要牢记一点：默认参数必须指向不变对象！**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['END']"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "['END']"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def add_end(L=None):#正确写法\n",
    "    if L is None:\n",
    "        L = []\n",
    "    L.append('END')\n",
    "    return L\n",
    "\n",
    "add_end()\n",
    "add_end()#这样就不会越加越多了"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 可变参数\n",
    "* 一般情况"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "def calc(numbers):\n",
    "    sum = 0\n",
    "    for n in numbers:\n",
    "        sum = sum + n * n\n",
    "    return sum"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 但是调用的时候，需要先组装出一个list或tuple："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "14"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "84"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "calc([1, 2, 3])#list\n",
    "calc((1, 3, 5, 7))#tuple\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用可变参数情况"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "def calc(*numbers):\n",
    "    sum = 0\n",
    "    for n in numbers:\n",
    "        sum = sum + n * n\n",
    "    return sum"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 这样就像多变量那样传参数就行了，在函数内部接收到的就是一个tuple"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "calc(1, 2)\n",
    "calc()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 但是如果已经有一个list或者tuple，要调用一个可变参数怎么办？  \n",
    " Python允许你在list或tuple前面加一个*号，把list或tuple的元素变成可变参数传进去：\n",
    "  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nums = [1, 2]\n",
    "calc(*nums)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 关键字参数(用字典传参的好手段！)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "name: Michael age: 30 other: {}\n",
      "name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer', 'school': '家里蹲大学'}\n",
      "name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer', 'school': '家里蹲大学'}\n"
     ]
    }
   ],
   "source": [
    "def person(name, age, **kkk):\n",
    "    print('name:', name, 'age:', age, 'other:', kkk)\n",
    "\n",
    "person('Michael', 30)#如果只传必选参数\n",
    "person('Adam', 45, gender='M', job='Engineer',school='家里蹲大学')#还可以加好多参数呢\n",
    "\n",
    "extra = {'gender':'M', 'job':'Engineer','school':'家里蹲大学'}#这些拼成一个字典\n",
    "person('Adam', 45, **extra)#和之前直接写参数是一样的\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 命名关键字参数(命名的意思是传参的时候要写参数名字？比如city='Beijing'？)\n",
    "* 可以检测你传入的关键字"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你传入了city\n",
      "name: Jack age: 24 other: {'city': 'Beijing', 'addr': 'Chaoyang', 'zipcode': 123456}\n"
     ]
    }
   ],
   "source": [
    "def person(name, age, **kw):\n",
    "    if 'city' in kw:\n",
    "        # 有city参数就过了\n",
    "        print(\"你传入了city\")\n",
    "        pass\n",
    "    if 'job' in kw:\n",
    "        # 有job参数\n",
    "        print(\"你传入了job\")\n",
    "        pass\n",
    "    print('name:', name, 'age:', age, 'other:', kw)\n",
    "\n",
    "person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 命名关键字参数\n",
    "* 和关键字参数**kw不同，命名关键字参数需要一个特殊分隔符*，*后面的参数被视为命名关键字参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Jack 24 Beijing Engineer\n"
     ]
    }
   ],
   "source": [
    "def person(name, age, *, city, job):\n",
    "    print(name, age, city, job)\n",
    "\n",
    "person('Jack', 24, city='Beijing', job='Engineer')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 如果函数定义中已经有了一个可变参数，后面跟着的命名关键字参数就不再需要一个特殊分隔符*了："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def person(name, age, *args, city, job):\n",
    "        print(name, age, args, city, job)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 命名关键字参数可以有缺省值，从而简化调用："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Jack 24 Beijing Engineer\n"
     ]
    }
   ],
   "source": [
    "def person(name, age, *,city='Beijing', job):\n",
    "      print(name, age, city, job)\n",
    "\n",
    "person('Jack', 24, job='Engineer')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 参数组合\n",
    "* 在Python中定义函数，可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数，这5种参数都可以组合使用。但是请注意，参数定义的顺序必须是：必选参数、默认参数、可变参数、命名关键字参数和关键字参数。\n",
    "\n",
    "比如定义一个函数，包含上述若干种参数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [],
   "source": [
    "def f1(a, b, c=0, *args, **kw):\n",
    "    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)\n",
    "\n",
    "def f2(a, b, c=0, *, d, **kw):\n",
    "    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "***以上在实战中理解吧，这样看有些麻烦***"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 递归函数\n",
    "### 简单的阶乘"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "120"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def fact(n):\n",
    "    if n==1:\n",
    "        return 1\n",
    "    return n * fact(n - 1)\n",
    "fact(5)#写个1000这里就栈溢出了"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 改成尾递归就不会溢出了？？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def fact(n):\n",
    "    return fact_iter(n, 1)\n",
    "\n",
    "def fact_iter(num, product):\n",
    "    if num == 1:\n",
    "        return product\n",
    "    return fact_iter(num - 1, num * product)\n",
    "\n",
    "fact(1000)#还真的是诶"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 知乎上讲得，很生动形象\n",
    "function story()  \n",
    " {    从前有座山，山上有座庙，庙里有个老和尚，一天老和尚对小和尚讲故事：story()  \n",
    "  // 尾递归，进入下一个函数不再需要上一个函数的环境了，得出结果以后直接返回。}  \n",
    "function story()   \n",
    "{    从前有座山，山上有座庙，庙里有个老和尚，一天老和尚对小和尚讲故事：story()，小和尚听了，找了块豆腐撞死了   \n",
    "// 非尾递归，下一个函数结束以后此函数还有后续，所以必须保存本身的环境以供处理返回值。}\n"
   ]
  }
 ],
 "metadata": {
  "interpreter": {
   "hash": "2e918aaa81d99c652401bdd1a0c185581595fb477ac919641bd65261b5d7782a"
  },
  "kernelspec": {
   "display_name": "Python 3.9.7 64-bit ('base': conda)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
